package com.vstyran.radio.managers
{
	import com.vstyran.radio.consts.AppConst;
	import com.vstyran.radio.consts.PostingType;
	import com.vstyran.radio.events.MusicEvent;
	import com.vstyran.radio.vos.MusicChunk;
	import com.vstyran.radio.vos.MusicMeta;
	import com.vstyran.radio.vos.MusicRequest;
	
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.NetStatusEvent;
	import flash.net.GroupSpecifier;
	import flash.net.NetConnection;
	import flash.net.NetGroup;
	import flash.net.NetStream;
	
	import mx.utils.ObjectUtil;
	
	
	[Event(name="bufferReady", type="com.vstyran.radio.events.MusicEvent")]
	[Event(name="bufferEmpty", type="com.vstyran.radio.events.MusicEvent")]
	
	[Event(name="connected", type="flash.events.Event")]
	public class RadioManager extends EventDispatcher
	{
		public const version:String = "0.0.2 alpha";
		
		[Bindable]
		public var connected:Boolean;
		
		[Bindable]
		public var info:String="";
		
		[Bindable("bufferSizeChanged")]
		public function get bufferSize():Number 
		{
			return buffer.length;
		}
		
		private var buffer:Vector.<MusicChunk> = new Vector.<MusicChunk>();
		
		public var netConnection:NetConnection;
		
		private var netGroup:NetGroup;
		
		private var netStream:NetStream;
		
		public var publisher:Boolean;
		
		public function initConnection():void
		{
			netConnection = new NetConnection();
			netConnection.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
			netConnection.connect("rtmfp://p2p.rtmfp.net/57136e5303f28e2972c080aa-44b77705c2ac/");
		}
		
		protected function netStatusHandler(event:NetStatusEvent):void
		{
			log(event.info.code);
			
			if(event.info.code == "NetConnection.Connect.Success")
			{
				peerId = netConnection.nearID;
				setupStream();
				dispatchEvent(new Event("connected"));
			}
		}
		
		public var groupName:String = "p2pRadioGroup";
		
		private function setupStream():void
		{
			var groupSpec:GroupSpecifier = new GroupSpecifier(groupName);
			groupSpec.serverChannelEnabled = true;
			groupSpec.multicastEnabled = true;
			groupSpec.postingEnabled = true;
			
			netGroup = new NetGroup(netConnection, groupSpec.groupspecWithAuthorizations());
			netGroup.addEventListener(NetStatusEvent.NET_STATUS, groupStatusHandler);			
			
			connected = true;
		}
		
		public function startBuffering():void
		{
			bufferEnabled = true;
		}
		
		public function stopBuffering():void
		{
			bufferEnabled = false;
			
			buffer.length = 0;
		}
		
		private var bufferEnabled:Boolean;
		
		[Bindable]
		public var peerId:String;
		
		[Bindable]
		public var currentSenderPeerId:String;
		
		protected function groupStatusHandler(event:NetStatusEvent):void
		{
			if(event.info.code == "NetGroup.Posting.Notify")
			{
				if(bufferEnabled)
				{
					if(!lastPlayedChunk || event.info.message.index >= lastPlayedChunk.index)
					{
						buffer.push(new MusicChunk(event.info.message.hostPeer,event.info.message.rating,event.info.message.trackName, event.info.message.index,event.info.message.bytes));
						buffer.sort(sortFunc);
						
						if(buffer.length >= AppConst.BUFFER_SIZE)
							dispatchEvent(new MusicEvent(MusicEvent.BUFFER_READY));
						
						dispatchEvent(new Event("bufferSizeChanged"));
					}
				}
				else if(event.info.message.type == PostingType.POST_TRACK_NAME)
				{
						trackName = event.info.message.name;
				}
				else if(event.info.message.type == PostingType.REQUEST_TRACK_NAME)
				{
				}
			}
			else
			{
				if(event.info.code == "NetGroup.Neighbor.Connect")
					numConnections++;
				
				if(event.info.code == "NetGroup.Neighbor.Disconnect")
					numConnections--;
				
				
				log(event.info.code);
			}
		}
		
		[Bindable]
		public var numConnections:Number = 0;
		
		[Bindable]
		public var trackName:String="";
		
		public function requestMusicName():void
		{
			netGroup.post(new MusicRequest(PostingType.REQUEST_TRACK_NAME));
		}
		
		public function post(chunk:MusicChunk):void
		{
			netGroup.post(chunk);
		}
		
		private var lastPlayedChunk:MusicChunk;
		
		public function extractBufferChunk():MusicChunk
		{
			lastPlayedChunk = buffer.shift();
			if(buffer.length == 0)
				dispatchEvent(new MusicEvent(MusicEvent.BUFFER_EMPTY));
			else
			{
				trackName = lastPlayedChunk.trackName;
				currentRating = lastPlayedChunk.rating;
				currentSenderPeerId = lastPlayedChunk.hostPeer;
			}
			
			dispatchEvent(new Event("bufferSizeChanged"));
			
			return lastPlayedChunk;
		}
		
		[Bindable]
		public var currentRating:Number=0;
		
		protected function log(text:String):void
		{
			info += text + "\n";
		}
		
		private function sortFunc(a:MusicChunk, b:MusicChunk):Number
		{
			return ObjectUtil.numericCompare(a.index, b.index);
		}
		
	}
}
